package kr.totalcall.business
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.OutputProgressEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.net.URLVariables;
	import flash.utils.ByteArray;
	
	import kr.totalcall.constant.TotalCallGlobals;
	import kr.totalcall.constant.URL;
	
	import mx.collections.XMLListCollection;
	import mx.controls.Alert;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	import mx.utils.StringUtil;

	/**
	 * 작업 기록
	 * 2012. 8. 14. / 이규광 / 최초 작성.
	 */
	/**
	 * 콜서버에서 받은 전화온 데이터를 받아서 처리한다.
	 * 
	 * @productversion Flex 4.5
	 * @langversion ActionScript 3.0
	 * @playerversion Flash 10.2
	 * @author 이규광.
	 */
	public class CallLinkerClient extends EventDispatcher
	{
		
		public static var serverIP:String = "192.168.0.10";
		public static var serverPort:int = 5882;
		
		public var sock:Socket;
		
		public var riderNumService:HTTPService;
		public var riderNumUv:URLVariables;
		
		public var callgroupTelListService:HTTPService;
		public var callgroupTelListUv:URLVariables;
		
		
		
		// 전화받은 히스토리..
		[Bindable] 
		public var receivedCallHistory:XMLListCollection = new XMLListCollection();
		
		public var connectable:Boolean = true;
		
		
		/**
		 * 생성자
		 */
		public function CallLinkerClient(ip:String= "192.168.0.10", port:int=5882 , isConnect:Boolean = true) {
			super();
			if(ip != ""){
				serverIP = ip;
			}
			serverPort = port;
			
		}
		
		
		
		/**
		 * 소캣을 초기화 한다.
		 */
		public function initSocket(ip:String, port:int, isConnect:Boolean = true):void{
			if(ip != ""){
				serverIP = ip;
			}
			if(!isNaN(port) ){
				serverPort = port;
			}
			
			connectable = isConnect;
			if(!connectable) return;
			
			if(!sock ) sock = new Socket();
			
			sock.addEventListener(Event.CONNECT, socketConnectHandler);
			sock.addEventListener(Event.CLOSE, socketCloseHandler);
			sock.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			sock.addEventListener(ProgressEvent.SOCKET_DATA, socketDataEventHandler);
			sock.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, outputProgressEventHandler);
			sock.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			
			
			callgroupTelListService = new HTTPService();
			callgroupTelListService.url = URL.urlMain + "/callGroupTelList.php";
			callgroupTelListService.addEventListener(ResultEvent.RESULT, callGroupTelList_resultHandler);
			getCallGroupTelList();
			
			riderNumService = new HTTPService();
			riderNumService.url = URL.urlMain + "/riderNumber.php";
			riderNumUv = new URLVariables();
			riderNumService.addEventListener(ResultEvent.RESULT, riderNumberServiceResultHandler);
			riderNumService.addEventListener(FaultEvent.FAULT, riderNumberServiceFaultHandler);
			
			if(isConnect){
				connect();
			}
		}
		
		
		[Bindable] public var connected:Boolean = false;
		
		
		/**
		 * 서버에 연결
		 */
		public function connect():void{
			if(!sock.connected)
				sock.connect(serverIP, serverPort);
				//sock.connect(serverIP, 5000);
			
		}
		
		
		protected function socketConnectHandler(event:Event):void{
			connected = true;
			TotalCallGlobals.main.receive.callLinkerConnBt.visible = false;
			TotalCallGlobals.main.receive.callLinkerConnBt.includeInLayout = false;
			dispatchEvent(new Event("connected"));
			trace(event.type);
			trace("콜링커와 연결되었습니다.");
			
		}
		
		protected function socketCloseHandler(event:Event):void{
			connected = false;
			TotalCallGlobals.main.receive.callLinkerConnBt.visible = true;
			TotalCallGlobals.main.receive.callLinkerConnBt.includeInLayout = true;
			trace(event.type);
			trace("콜링커와 연결이 끊겼습니다.");
		}
		
		
		
		protected var callInfoXML:XML = null;
		
		// 땡겨받았을 경우 앞뒤 값을 체크해야 하므로 아래 변수를 활용..
		protected var beforeInfo:XML = null;
		
		
		protected var isRefreshData:Boolean = false;
		
		/**
		 * input handler
		 */
		protected function socketDataEventHandler(event:ProgressEvent):void{
			if(TotalCallGlobals.isDebug) return;
			
			var msg:String = sock.readMultiByte(event.bytesLoaded, "utf-8");
			//trace("msg :: " + msg);
			var policyCheckStr:String = "<cross-domain-policy>";
			var helloMsg:String = "CallLinker Server message : hello..";
			
			if(msg.indexOf(policyCheckStr ) != -1){
				// 정책파일 처리..
				//trace("Flex Policy check:" + msg);
				//sock.writeMultiByte("ok", "utf-8");
				
				//if(!TotalCallGlobals.isDebug){
					sendMenssage("getHistoryData" );
				//}
				return;
			}
			
			if(msg.indexOf(helloMsg) != -1){
				//trace(msg);
				return;
			}
			
			
			var refrechDataStart:String = "<refreshdata>";
			var refrechDataEnd:String = "</refreshdata>";
			
			
			if(msg.indexOf(refrechDataStart) != -1){
				refreshHistoryStringData = "";
				isRefreshData = true;
				if(TotalCallGlobals.isDebug){ 
					trace(":::::::::: start refresh data ::::::::::"); 
				}
				
				if(StringUtil.trim(msg) != refrechDataStart){
					var tmpData:String = msg.replace(refrechDataStart, "");
					if(TotalCallGlobals.isDebug){ 
						trace(":::::::::: start and data refresh data ::::::::::"); 
					}
					
					if(tmpData.indexOf(refrechDataEnd) != -1){
						tmpData.replace(refrechDataEnd, "");
						
						addRefreahHistoryData(tmpData);
						//receivedCallHistory.refresh();
						isRefreshData = false;
						if(TotalCallGlobals.isDebug){ 
							trace(":::::::::: start-end refresh data ::::::::::"); 
						}
						parseRefreahHistoryData();
						return;
					}
					addRefreahHistoryData(tmpData);
					return;
				}else{
					if(TotalCallGlobals.isDebug){ 
						trace(":::::::::: start no refresh data ::::::::::"); 
					}
					return;
				}
				
			}else if( msg.indexOf(refrechDataEnd) != -1 ){
				
				if(TotalCallGlobals.isDebug){ 
					trace(":::::::::: end refresh data ::::::::::"); 
				}
				if(StringUtil.trim(msg) != refrechDataEnd){
					if(TotalCallGlobals.isDebug){ 
						trace(":::::::::: end and data refresh data ::::::::::"); 
					}
					var tmpData:String = msg.replace(refrechDataEnd, "");
					addRefreahHistoryData(tmpData);
					//receivedCallHistory.refresh();
					
					isRefreshData = false;
					parseRefreahHistoryData();
					
					return;
				}else{
					if(TotalCallGlobals.isDebug){ 
						trace(":::::::::: end no refresh data ::::::::::"); 
					}
					isRefreshData = false;
					parseRefreahHistoryData();
					return;
				}
			}
			
			if(isRefreshData){
				if(TotalCallGlobals.isDebug){ 
					trace(":::::::::: only refresh data ::::::::::"); 
				}
				addRefreahHistoryData(msg);
				return ;
			}
			
			/*
			//리프레쉬 데이터..
			if(msg.indexOf(refrechData) != -1){
				msg = msg.substr(refrechData.length);
				var refreshXMLList:XMLList = new XMLList(msg);
				receivedCallHistory.removeAll();
				receivedCallHistory.source = refreshXMLList;
				
				var dialedDigit:String = "";
				for(var j : int = 0; j < receivedCallHistory.length; j++){
					
					if(receivedCallHistory[j].branch_name.toString() != "") continue;
					
					dialedDigit = StringUtil.trim( receivedCallHistory[j].strDIALED_DIGIT);
					var branchName:String = getCallGroupTelOfBranch(dialedDigit);
					if(!branchName || branchName == ""){
						receivedCallHistory[j].branch_name = TotalCallGlobals.userBranchName;
					}else{
						receivedCallHistory[j].branch_name = branchName;
					}
				}
				
				receivedCallHistory.refresh();
				return;
			}*/
			
			
			//trace("isRefreshData : " + isRefreshData);
			var xmlList:XMLList = null;
			try{
				xmlList = new XMLList(msg);
			}catch(error:Error){
				trace("msg:" + msg);
				trace(error.message);
			}
			callInfoXML = null;
			
			//trace("call linker server received xml length : " + xmlList.length());
			for(var i : int = 0 ; i < xmlList.length(); i++){
				
				callInfoXML = xmlList[i];
				
				callReceived(callInfoXML);
				
				/*
				if(callInfoXML.FG == "IT" ){
					
					callReceived(callInfoXML);
					
				}else if(callInfoXML.FG == "IA" ){
					if(callInfoXML.DIALED_DIGIT.toString() == "454"){
						callReceived(callInfoXML);
					}else if(beforeInfo && beforeInfo.FG.toString() == "PU"){
						callReceived(beforeInfo);
					}
					
				}else if(callInfoXML.FG == "PU" ){
					// 땡겨받았을 경우..
					if(beforeInfo && beforeInfo.FG.toString() == "TT"){
						beforeInfo.EXT = callInfoXML.EXT;
						callReceived(beforeInfo);
					}
					
				}
				*/
				beforeInfo = null;
				beforeInfo = xmlList[i];
				/*
				trace(callInfoXML.STT_TIME.toString() +  " [" + callInfoXML.FG.toString() + "] " +
					"EXT:" + callInfoXML.EXT.toString() + ", " +
					"TRK:" + callInfoXML.TRK.toString() + ", " +
					"DIALED_DIGIT:" + callInfoXML.DIALED_DIGIT.toString() + ", " + 
					"CLIP_NUM:" + callInfoXML.CLIP_NUM.toString()
				);*/
			}
			
			//sock.flush();
		}
		
		
		
		protected var refreshHistoryStringData:String = "";
		
		/**
		 * refresh data를 history 내역에 추가한다.
		 */
		protected function addRefreahHistoryData(xmlStrData:String):void{
			refreshHistoryStringData += xmlStrData;
			return ;
			/*
			if(StringUtil.trim(xmlStrData) == ""){
				return;
			}
			var refreshXMLList:XMLList = null;
			try{
				refreshXMLList = new XMLList(xmlStrData);
			}catch(e:Error){
				trace("xmlStrData(" +xmlStrData + ")");
			}
			if(!refreshXMLList) {
				trace("addRefreahHistoryData - refreshXMLList is null \n data=" + xmlStrData);
				return;
			}
			
			for(var j :int = 0; j < refreshXMLList.length(); j++){
				
				if(refreshXMLList[j].branch_name.toString() == ""){
					var dialedDigit:String = StringUtil.trim( refreshXMLList[j].strDIALED_DIGIT);
					var branchName:String = getCallGroupTelOfBranch(dialedDigit);
					if(!branchName || branchName == ""){
						refreshXMLList[j].branch_name = TotalCallGlobals.userBranchName;
					}else{
						refreshXMLList[j].branch_name = branchName;
					}
				}
				receivedCallHistory.addItem(refreshXMLList[j]);
			}*/
		}
		
		protected function parseRefreahHistoryData():void{
			
			var xmlStrData :String = refreshHistoryStringData;
			//trace(xmlStrData);
			
			if(StringUtil.trim(xmlStrData) == ""){
				return;
			}
			var refreshXMLList:XMLList = null;
			try{
				refreshXMLList = new XMLList(xmlStrData);
			}catch(e:Error){
				//trace("xmlStrData(" +xmlStrData + ")");
			}
			if(!refreshXMLList) {
				//trace("addRefreahHistoryData - refreshXMLList is null \n data=" + xmlStrData);
				return;
			}
			
			for(var j :int = 0; j < refreshXMLList.length(); j++){
				
				if(refreshXMLList[j].branch_name.toString() == ""){
					var dialedDigit:String = StringUtil.trim( refreshXMLList[j].strDIALED_DIGIT);
					var branchName:String = getCallGroupTelOfBranch(dialedDigit);
					if(!branchName || branchName == ""){
						refreshXMLList[j].branch_name = TotalCallGlobals.userBranchName;
					}else{
						refreshXMLList[j].branch_name = branchName;
					}
				}
				receivedCallHistory.addItem(refreshXMLList[j]);
			}
			receivedCallHistory.refresh();
			trace("end of recevied call history refresh data. total " + receivedCallHistory.length + "rows");
		}
		
		
		
		/**
		 * 전화 받았으므로 접수창을 띄움..
		 */
		protected function callReceived(infoXML:XML):void{
			var branchName:String = getCallGroupTelOfBranch(StringUtil.trim( infoXML.DIALED_DIGIT));
			infoXML.branch_name = (branchName != "" ? branchName : TotalCallGlobals.userBranchName);
			//trace(infoXML.branch_name.toString());
			receivedCallHistory.addItemAt(infoXML, 0);
			//receivedCallHistory.refresh();
			
			//TotalCallGlobals.main.receive.callHistory.historyDG.dataProvider = receivedCallHistory;
			
			
			//Alert.show(infoXML.EXT.toString() + "[" + TotalCallGlobals.keyphoneNum.toString() + "]");
			//if(TotalCallGlobals.isDebug || infoXML.EXT == TotalCallGlobals.keyphoneNum ){
			//if(TotalCallGlobals.isDebug || StringUtil.trim(infoXML.EXT) == StringUtil.trim(TotalCallGlobals.keyphoneNum) ){
			if(StringUtil.trim(infoXML.EXT) == StringUtil.trim(TotalCallGlobals.keyphoneNum) ){
				// 접수창 띄우기..
				//trace(infoXML.EXT.toString() + " 전화받음 - " + infoXML.CLIP_NUM);
				
				var telNum:String = StringUtil.trim(infoXML.CLIP_NUM);
				if(telNum == "") return;
				
				/*
				if(StringUtil.trim(infoXML.DIALED_DIGIT) == "454"){		// 기사 전화인 경우
					riderNumUv.phone = telNum;
					riderNumService.send(riderNumUv);
					
				}else{
					TotalCallGlobals.main.receive.btnReceive_click2(telNum);
				}
				*/
				
				//TotalCallGlobals.main.receive.btnReceive_click2(telNum);
				TotalCallGlobals.main.receive.existRiderNum(infoXML);
			}
		}
		
		
		
		protected function riderNumberServiceResultHandler(event:ResultEvent):void{
			if(event.result.toString() == "") return;
			//라이더 검색
			TotalCallGlobals.main.receive.dropSearch.selectedIndex = 2;
			TotalCallGlobals.main.receive.inputSearch.text = event.result.toString();
			TotalCallGlobals.main.receive.btnSearch_click();
		}
		
		protected function riderNumberServiceFaultHandler(event:FaultEvent):void{
			trace(event.message);
		}
		
		
		/**
		 * output 
		 */
		protected function outputProgressEventHandler(event:OutputProgressEvent):void{
			trace(event.type);
			trace("보낸메세지..");
		}
		
		
		
		
		
		
		/**
		 * io error
		 */
		protected function ioErrorHandler(event:IOErrorEvent):void{
			connected = false;
			TotalCallGlobals.main.receive.callLinkerConnBt.visible = true;
			TotalCallGlobals.main.receive.callLinkerConnBt.includeInLayout = true;
			trace(event.type);
			trace("데이터를 처리하는 중 에러가 발생했습니다.");
		}
		
		
		/**
		 * security error
		 */
		protected function securityErrorHandler(event:SecurityErrorEvent):void{
			connected = false;
			TotalCallGlobals.main.receive.callLinkerConnBt.visible = true;
			TotalCallGlobals.main.receive.callLinkerConnBt.includeInLayout = true;
			trace(event.type);
			trace("보안 에러가 발생했습니다.");
		}
		
		
		//========================================================================================
		// Message Send
		//========================================================================================
		public function sendMenssage(msg:String):void{
			if(!msg || msg == "" )return ;
			if(!sock.connected){
				trace("콜링커와 연결되어 있지 않습니다.");
				return;
			}
			sock.writeMultiByte(msg+"\n", "UTF-8");
			sock.flush();
		}
		
		
		//========================================================================================
		// 콜그룹 관련..
		//========================================================================================
		
		public var callGroupTelListXC:XMLListCollection ;
		
		public function getCallGroupTelList():void{
			//trace("TotalCallGlobals.callGroupNum:"+TotalCallGlobals.callGroupNum);
			if(!TotalCallGlobals.callGroupNum || TotalCallGlobals.callGroupNum == "-1") return;
			
			var uv:URLVariables = new URLVariables();
			uv.callgroup_num = TotalCallGlobals.callGroupNum;
			uv.is_all = "true";
			callgroupTelListService.method = "post";
			callgroupTelListService.resultFormat = HTTPService.RESULT_FORMAT_E4X;
			callgroupTelListService.send(uv);
		}
		
		protected function callGroupTelList_resultHandler(event:ResultEvent):void
		{
			callGroupTelListXC = new XMLListCollection(event.result.record);
		}
		
		/**
		 * 국선번호를 찾아 해당 국선번호로 지정된 branch name을 리턴함
		 */
		public function getCallGroupTelOfBranch(dialdDigit:String):String{
			dialdDigit = StringUtil.trim(dialdDigit);
			if(!callGroupTelListXC) return "";
			if( dialdDigit == ""){
				for(var j:int = 0; j < callGroupTelListXC.length; j++){
					var bName:String = "";
					if(callGroupTelListXC[j].in_tel == "" && callGroupTelListXC[j].inout_exct_yn == "Y"){
						bName = callGroupTelListXC[j].branch_name;
					}
					return bName;
				}
			}
			
			var startStrIdx:int = 4 - dialdDigit.length;
			
			for(var i : int = 0 ; i < callGroupTelListXC.length; i++){
				
				if(startStrIdx != 0){
					if(callGroupTelListXC[i].in_tel.substr(startStrIdx) == dialdDigit){
						//trace("국선 찾음:" + callGroupTelListXC[i].branch_name + " " + dialdDigit);
						return callGroupTelListXC[i].branch_name;
					}
				}else{
					if(callGroupTelListXC[i].in_tel == dialdDigit){
						//trace("국선 찾음:" + callGroupTelListXC[i].branch_name + " " + dialdDigit);
						return callGroupTelListXC[i].branch_name;
					}
				}
			}
			return "";
		}
		
	}
}